from fastapi import APIRouter, Depends, Request, HTTPException
from fastapi.responses import JSONResponse
import asyncio
import logging
import time
from datetime import datetime
from sqlalchemy.orm import Session

from app.db.session import get_db
from app.models.models import User, Video, Voice, Job, JobV2
from app.services.external_api_v2 import create_digital_person_v2, create_voice_clone_v2, create_videomix_v2
from app.core.config import settings
from app.utils.youshuai import ApiClient
from app.core.logging_config import get_v2_logger, get_external_api_logger, get_db_logger

router = APIRouter()

# 初始化优速AI客户端
youshu_ai = ApiClient()

# 获取专用日志记录器
v2_logger = get_v2_logger()
external_api_logger = get_external_api_logger()
db_logger = get_db_logger()

# V2版本 - 创建数字人接口
@router.post("/v2/video/create")
async def create_digital_human_v2_endpoint(request: Request, db: Session = Depends(get_db)):
    """
    V2版本 - 创建数字人接口（参数和V1保持一致，包含token验证和扣费）
    """
    request_id = f"V2_VIDEO_{int(time.time() * 1000)}"
    v2_logger.info(f"[{request_id}] ===== V2数字人创建请求开始 =====")
    v2_logger.info(f"[{request_id}] 收到请求：{request.method} {request.url.path}")
    v2_logger.info(f"[{request_id}] 客户端IP: {request.client.host if request.client else 'Unknown'}")
    
    # 记录请求头
    headers_dict = dict(request.headers)
    v2_logger.info(f"[{request_id}] 请求头: {headers_dict}")

    # 验证 Content-Type
    if request.headers.get('content-type') != 'application/json':
        v2_logger.error(f"[{request_id}] Content-Type 非 application/json")
        raise HTTPException(status_code=400, detail='Content-Type must be application/json')
    
    # 提取 headers 中的 token 值
    token = request.headers.get('Authorization')
    if not token:
        v2_logger.error(f"[{request_id}] 请求头中缺少 Authorization token")
        return JSONResponse(status_code=401, content={"code": 401, "msg": "缺少 Authorization token"})

    v2_logger.info(f"[{request_id}] 提取到的 token: {token}")
    print("token:", token)

    # 验证token并扣除点数 - 使用项目ID 46（与V1数字人创建保持一致）
    v2_logger.info(f"[{request_id}] 开始验证token，项目ID: 46")
    user_info = youshu_ai.get_current_user_information(project=46, token=token)
    v2_logger.info(f"[{request_id}] 优速AI验证结果: {user_info}")
    print("user_info:", user_info)

    # 从 user_info 中获取统一的 code 和 msg
    code = user_info.get("code", 500)  # 如果没拿到 code，就默认为 500
    msg = user_info.get("msg", "未知错误")

    # 根据 code 判断是否继续执行
    if code == 200:
        # 表示验证成功，可以继续后续逻辑
        verify_taskId = user_info.get("taskId")
        jssign = user_info.get("jssign")
        v2_logger.info(f"[{request_id}] Token验证成功，taskId: {verify_taskId}, jssign: {jssign}")
    else:
        # 只要 code != 200，就将错误直接返回给前端
        v2_logger.error(f"[{request_id}] Token验证失败: code={code}, msg={msg}")
        return JSONResponse(status_code=code, content={"code": code, "msg": msg})

    # 解析 JSON 数据
    try:
        data = await request.json()
        v2_logger.info(f"[{request_id}] 接收到的数据：{data}")
    except Exception as e:
        v2_logger.error(f"[{request_id}] 请求体中缺少 JSON 数据：{e}")
        raise HTTPException(status_code=400, detail='Missing JSON data in request body')

    # 提取参数（和V1保持一致）
    name_id = data.get('name_id')
    video_url = data.get('video_url')
    title = data.get('title')

    v2_logger.info(f"[{request_id}] 解析参数 - name_id: {name_id}, video_url: {video_url}, title: {title}")

    if not all([name_id, video_url, title]):
        v2_logger.error(f"[{request_id}] 缺少必要参数")
        return JSONResponse(status_code=400, content={'error': 'name_id, video_url, title are required'})

    # 检查用户是否存在，不存在则创建
    user = db.query(User).filter(User.name_id == name_id).first()
    if not user:
        v2_logger.info(f"[{request_id}] 用户不存在，自动为其创建用户记录，name_id={name_id}")
        db_logger.info(f"[{request_id}] 创建新用户: {name_id}")
        user = User(name_id=name_id)
        db.add(user)
        db.commit()
        db.refresh(user)
        v2_logger.info(f"[{request_id}] 已创建新用户，name_id={user.name_id}")
    else:
        db_logger.info(f"[{request_id}] 用户已存在: {name_id}")

    # 构建外部API调用数据
    external_data = {
        'name': title,
        'url': video_url,
        'callback': settings.V2_CALLBACK_URL
    }
    v2_logger.info(f"[{request_id}] 构建外部API调用数据: {external_data}")

    # 调用V2版本的外部 API 创建数字人
    try:
        external_api_logger.info(f"[{request_id}] 开始调用V2外部API创建数字人")
        external_api_logger.info(f"[{request_id}] API地址: {settings.EXTERNAL_API_V2_URL}")
        external_api_logger.info(f"[{request_id}] 发送数据: {external_data}")
        
        response_data, status_code = await create_digital_person_v2(external_data)
        
        external_api_logger.info(f"[{request_id}] V2外部API响应：状态码={status_code}, 数据={response_data}")
        v2_logger.info(f"[{request_id}] V2外部API响应：状态码={status_code}, 数据={response_data}")
        
        if status_code == 200:
            # 如果外部API调用成功，将任务信息保存到数据库
            try:
                current_time = int(time.time())
                db_logger.info(f"[{request_id}] 开始数据库操作，当前时间戳: {current_time}")
                
                # 检查用户是否存在，不存在则创建
                user = db.query(User).filter(User.name_id == name_id).first()
                if not user:
                    user = User(name_id=name_id)
                    db.add(user)
                    db.commit()
                    db_logger.info(f"[{request_id}] 创建新用户: {name_id}")
                    v2_logger.info(f"[{request_id}] 创建新用户: {name_id}")
                else:
                    db_logger.info(f"[{request_id}] 用户已存在: {name_id}")
                
                # 创建视频记录（临时状态，等待回调更新）
                new_video = Video(
                    name_id=name_id,
                    video_url=video_url,  # 先保存原始URL，回调时更新
                    title=title,
                    time=current_time
                )
                db.add(new_video)
                db.commit()
                
                db_logger.info(f"[{request_id}] V2数字人记录已保存到数据库 - 用户: {name_id}, 标题: {title}, 视频ID: {new_video.id}")
                v2_logger.info(f"[{request_id}] V2数字人创建任务已保存到数据库 - 用户: {name_id}, 标题: {title}")
                
                # 通知优速AI任务成功（与V1保持一致的处理方式）
                try:
                    v2_logger.info(f"[{request_id}] 开始通知优速AI任务成功，taskId: {verify_taskId}")
                    response = youshu_ai.build_status(task_id=verify_taskId, status='success', remake='V2数字人创建成功')
                    v2_logger.info(f"[{request_id}] V2数字人创建成功并回调：{response}")
                    print("V2数字人创建成功并回调：", response)
                except Exception as callback_error:
                    v2_logger.error(f"[{request_id}] 通知优速AI失败: {callback_error}")
                
            except Exception as e:
                db_logger.error(f"[{request_id}] 保存到数据库时出错：{e}")
                v2_logger.error(f"[{request_id}] 保存到数据库时出错：{e}")
                db.rollback()
                # 通知优速AI任务失败
                try:
                    youshu_ai.build_status(task_id=verify_taskId, status='failed', remake=f'V2数字人创建失败: {str(e)}')
                    v2_logger.info(f"[{request_id}] 已通知优速AI任务失败")
                except Exception as callback_error:
                    v2_logger.error(f"[{request_id}] 通知优速AI失败: {callback_error}")
                return JSONResponse(status_code=500, content={'error': 'Database error'})
            
            v2_logger.info(f"[{request_id}] ===== V2数字人创建请求成功完成 =====")
            return JSONResponse(status_code=200, content={'code': 200, 'message': 'Digital human creation started'})
        else:
            external_api_logger.error(f"[{request_id}] V2外部API请求失败，状态码：{status_code}")
            v2_logger.error(f"[{request_id}] V2外部API请求失败，状态码：{status_code}")
            # 通知优速AI任务失败
            try:
                youshu_ai.build_status(task_id=verify_taskId, status='failed', remake=f'V2外部API调用失败，状态码: {status_code}')
                v2_logger.info(f"[{request_id}] 已通知优速AI任务失败")
            except Exception as callback_error:
                v2_logger.error(f"[{request_id}] 通知优速AI失败: {callback_error}")
            return JSONResponse(status_code=status_code, content=response_data)
            
    except Exception as e:
        external_api_logger.error(f"[{request_id}] 调用V2外部 API 时出错：{e}")
        v2_logger.error(f"[{request_id}] 调用V2外部 API 时出错：{e}")
        # 通知优速AI任务失败
        try:
            youshu_ai.build_status(task_id=verify_taskId, status='failed', remake=f'V2外部API调用异常: {str(e)}')
            v2_logger.info(f"[{request_id}] 已通知优速AI任务失败")
        except Exception as callback_error:
            v2_logger.error(f"[{request_id}] 通知优速AI失败: {callback_error}")
        return JSONResponse(status_code=500, content={'error': 'External API error'})


# V2版本 - 创建声音克隆接口
@router.post("/v2/voice/create")
async def create_voice_clone_v2_endpoint(request: Request, db: Session = Depends(get_db)):
    """
    V2版本 - 创建声音克隆接口
    """
    request_id = f"V2_VOICE_{int(time.time() * 1000)}"
    v2_logger.info(f"[{request_id}] ===== V2声音克隆创建请求开始 =====")
    v2_logger.info(f"[{request_id}] 收到请求：{request.method} {request.url.path}")
    v2_logger.info(f"[{request_id}] 客户端IP: {request.client.host if request.client else 'Unknown'}")
    
    # 记录请求头
    headers_dict = dict(request.headers)
    v2_logger.info(f"[{request_id}] 请求头: {headers_dict}")

    # 验证 Content-Type
    if request.headers.get('content-type') != 'application/json':
        v2_logger.error(f"[{request_id}] Content-Type 非 application/json")
        raise HTTPException(status_code=400, detail='Content-Type must be application/json')
    
    # 提取 headers 中的 token 值
    token = request.headers.get('Authorization')
    if not token:
        v2_logger.error(f"[{request_id}] 请求头中缺少 Authorization token")
        return JSONResponse(status_code=401, content={"code": 401, "msg": "缺少 Authorization token"})

    v2_logger.info(f"[{request_id}] 提取到的 token: {token}")
    print("token:", token)

    # 验证token并扣除点数 - 使用项目ID 47（参考V1声音训练）
    v2_logger.info(f"[{request_id}] 开始验证token，项目ID: 47")
    user_info = youshu_ai.get_current_user_information(project=47, token=token)
    v2_logger.info(f"[{request_id}] 优速AI验证结果: {user_info}")
    print("user_info:", user_info)

    # 从 user_info 中获取统一的 code 和 msg
    code = user_info.get("code", 500)  # 如果没拿到 code，就默认为 500
    msg = user_info.get("msg", "未知错误")

    # 根据 code 判断是否继续执行
    if code == 200:
        # 表示验证成功，可以继续后续逻辑
        verify_taskId = user_info.get("taskId")
        jssign = user_info.get("jssign")
        v2_logger.info(f"[{request_id}] Token验证成功，taskId: {verify_taskId}, jssign: {jssign}")
    else:
        # 只要 code != 200，就将错误直接返回给前端
        v2_logger.error(f"[{request_id}] Token验证失败: code={code}, msg={msg}")
        return JSONResponse(status_code=code, content={"code": code, "msg": msg})

    # 解析 JSON 数据
    try:
        data = await request.json()
        v2_logger.info(f"[{request_id}] 接收到的数据：{data}")
    except Exception as e:
        v2_logger.error(f"[{request_id}] 请求体中缺少 JSON 数据：{e}")
        raise HTTPException(status_code=400, detail='Missing JSON data in request body')

    # 提取参数
    name_id = data.get('name_id')
    audio_url = data.get('audio_url')
    title = data.get('title')
    voice_type = data.get('voiceType', settings.EXTERNAL_VOICE_V2_TYPE)  # 可选参数，使用配置默认值

    v2_logger.info(f"[{request_id}] 解析参数 - name_id: {name_id}, audio_url: {audio_url}, title: {title}, voiceType: {voice_type}")

    if not all([name_id, audio_url, title]):
        v2_logger.error(f"[{request_id}] 缺少必要参数")
        return JSONResponse(status_code=400, content={'error': 'name_id, audio_url, title are required'})

    # 检查用户是否存在，不存在则创建
    user = db.query(User).filter(User.name_id == name_id).first()
    if not user:
        v2_logger.info(f"[{request_id}] 用户不存在，自动为其创建用户记录，name_id={name_id}")
        db_logger.info(f"[{request_id}] 创建新用户: {name_id}")
        user = User(name_id=name_id)
        db.add(user)
        db.commit()
        db.refresh(user)
        v2_logger.info(f"[{request_id}] 已创建新用户，name_id={user.name_id}")
    else:
        db_logger.info(f"[{request_id}] 用户已存在: {name_id}")

    # 构建外部API调用数据
    external_data = {
        'name': title,
        'url': audio_url,
        'voiceType': voice_type,
        'callback': settings.V2_VOICE_CALLBACK_URL
    }
    v2_logger.info(f"[{request_id}] 构建外部API调用数据: {external_data}")

    # 调用V2版本的外部 API 创建声音克隆
    try:
        external_api_logger.info(f"[{request_id}] 开始调用V2声音克隆API")
        external_api_logger.info(f"[{request_id}] API地址: {settings.EXTERNAL_VOICE_V2_URL}")
        external_api_logger.info(f"[{request_id}] 发送数据: {external_data}")
        
        response_data, status_code = await create_voice_clone_v2(external_data)
        
        external_api_logger.info(f"[{request_id}] V2声音克隆API响应：状态码={status_code}, 数据={response_data}")
        v2_logger.info(f"[{request_id}] V2声音克隆API响应：状态码={status_code}, 数据={response_data}")
        
        if status_code == 200:
            # 如果外部API调用成功，将任务信息保存到数据库
            try:
                current_time = int(time.time())
                db_logger.info(f"[{request_id}] 开始数据库操作，当前时间戳: {current_time}")
                
                # 获取外部API返回的jobId作为voice_id
                job_id = response_data.get('data', {}).get('jobId')
                if not job_id:
                    v2_logger.error(f"[{request_id}] 外部API未返回jobId")
                    external_api_logger.error(f"[{request_id}] 外部API未返回jobId，响应数据: {response_data}")
                    # 通知优速AI任务失败
                    youshu_ai.build_status(task_id=verify_taskId, status='failed', remake='外部API未返回jobId')
                    return JSONResponse(status_code=500, content={'error': 'External API did not return jobId'})
                
                v2_logger.info(f"[{request_id}] 获取到jobId: {job_id}")
                
                # 创建声音记录（临时状态，等待回调更新）
                # 注意：如果数据库中还没有task_id字段，需要先执行SQL脚本添加字段
                try:
                    new_voice = Voice(
                        name_id=name_id,
                        voice_id=job_id,  # 使用外部API返回的jobId
                        type=2,  # V2版本声音类型
                        voice_type=1,  # 默认声音类型
                        title=title,
                        audio_url=audio_url,  # 先保存原始URL，回调时可能更新
                        task_id=verify_taskId,  # 保存taskId用于回调通知
                        v2_voice_type=voice_type,  # 保存V2版本的voiceType参数（pro/lite）
                        time=current_time
                    )
                    db.add(new_voice)
                    db.commit()
                    
                    db_logger.info(f"[{request_id}] V2声音记录已保存到数据库 - 用户: {name_id}, 标题: {title}, JobID: {job_id}, TaskID: {verify_taskId}, VoiceType: {voice_type}, 声音ID: {new_voice.id}")
                    v2_logger.info(f"[{request_id}] V2声音克隆任务已保存到数据库 - 用户: {name_id}, 标题: {title}, JobID: {job_id}, TaskID: {verify_taskId}, VoiceType: {voice_type}")
                    
                except Exception as db_error:
                    if "Unknown column" in str(db_error):
                        # 如果字段不存在，使用兼容模式，先回滚当前事务
                        db.rollback()
                        v2_logger.warning(f"[{request_id}] 数据库中缺少字段，请执行SQL脚本添加：task_id、speaker_id和v2_voice_type")
                        db_logger.warning(f"[{request_id}] 数据库缺少字段，使用兼容模式保存")
                        
                        try:
                            new_voice = Voice(
                                name_id=name_id,
                                voice_id=job_id,
                                type=2,
                                voice_type=1,
                                title=title,
                                audio_url=audio_url,
                                time=current_time
                            )
                            db.add(new_voice)
                            db.commit()
                            db_logger.info(f"[{request_id}] V2声音记录已保存到数据库（兼容模式） - 用户: {name_id}, 标题: {title}, JobID: {job_id}, 声音ID: {new_voice.id}")
                            v2_logger.info(f"[{request_id}] V2声音克隆任务已保存到数据库（兼容模式） - 用户: {name_id}, 标题: {title}, JobID: {job_id}")
                        except Exception as compat_error:
                            db_logger.error(f"[{request_id}] 兼容模式保存也失败：{compat_error}")
                            db.rollback()
                            raise compat_error
                    else:
                        raise db_error
            
            except Exception as e:
                db_logger.error(f"[{request_id}] 保存到数据库时出错：{e}")
                v2_logger.error(f"[{request_id}] 保存到数据库时出错：{e}")
                db.rollback()
                # 通知优速AI任务失败
                try:
                    youshu_ai.build_status(task_id=verify_taskId, status='failed', remake=f'V2声音克隆数据库保存失败: {str(e)}')
                    v2_logger.info(f"[{request_id}] 已通知优速AI任务失败 - TaskID: {verify_taskId}")
                except Exception as notify_error:
                    v2_logger.error(f"[{request_id}] 通知优速AI失败: {notify_error}")
                return JSONResponse(status_code=500, content={'error': 'Database error'})
            
            v2_logger.info(f"[{request_id}] ===== V2声音克隆请求成功完成 =====")
            return JSONResponse(status_code=200, content={'code': 200, 'message': 'Voice clone creation started', 'data': {'jobId': job_id}})
        else:
            external_api_logger.error(f"[{request_id}] V2声音克隆API请求失败，状态码：{status_code}")
            v2_logger.error(f"[{request_id}] V2声音克隆API请求失败，状态码：{status_code}")
            # 通知优速AI任务失败
            try:
                youshu_ai.build_status(task_id=verify_taskId, status='failed', remake=f'V2声音克隆外部API调用失败，状态码: {status_code}')
                v2_logger.info(f"[{request_id}] 已通知优速AI任务失败 - TaskID: {verify_taskId}")
            except Exception as notify_error:
                v2_logger.error(f"[{request_id}] 通知优速AI失败: {notify_error}")
            return JSONResponse(status_code=status_code, content=response_data)
            
    except Exception as e:
        external_api_logger.error(f"[{request_id}] 调用V2声音克隆API时出错：{e}")
        v2_logger.error(f"[{request_id}] 调用V2声音克隆API时出错：{e}")
        # 通知优速AI任务失败
        try:
            youshu_ai.build_status(task_id=verify_taskId, status='failed', remake=f'V2声音克隆外部API调用异常: {str(e)}')
            v2_logger.info(f"[{request_id}] 已通知优速AI任务失败 - TaskID: {verify_taskId}")
        except Exception as notify_error:
            v2_logger.error(f"[{request_id}] 通知优速AI失败: {notify_error}")
        return JSONResponse(status_code=500, content={'error': 'External API error'})


# V2版本 - 数字人创建回调接口
@router.post("/v2/callback")
async def digital_person_callback_v2(request: Request, db: Session = Depends(get_db)):
    """
    V2版本 - 接收数字人创建回调
    """
    callback_id = f"V2_CALLBACK_{int(time.time() * 1000)}"
    v2_logger.info(f"[{callback_id}] ===== 收到V2数字人回调请求 [{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] =====")
    v2_logger.info(f"[{callback_id}] 客户端IP: {request.client.host if request.client else 'Unknown'}")
    
    # 记录请求头
    headers_dict = dict(request.headers)
    v2_logger.info(f"[{callback_id}] 请求头: {headers_dict}")

    # 解析回调数据
    try:
        callback_data = await request.json()
        v2_logger.info(f"[{callback_id}] 回调数据: {callback_data}")
    except Exception as e:
        v2_logger.error(f"[{callback_id}] 解析回调数据失败：{e}")
        return JSONResponse(status_code=400, content={'error': 'Invalid JSON data'})

    # 提取回调数据字段
    person_id = callback_data.get('id')
    create_at = callback_data.get('createAt')
    name = callback_data.get('name')
    url = callback_data.get('url')
    status = callback_data.get('status')
    platform = callback_data.get('platform')
    callback_url = callback_data.get('callback')
    from_source = callback_data.get('from')

    v2_logger.info(f"[{callback_id}] 回调数据解析 - ID: {person_id}, 状态: {status}, 名称: {name}, URL: {url}")

    # 处理回调逻辑
    try:
        if status == "SUCCESS":
            # 数字人创建成功，更新数据库中的视频记录
            # 根据标题查找对应的视频记录进行更新
            db_logger.info(f"[{callback_id}] 开始查找数字人记录，标题: {name}")
            video_record = db.query(Video).filter(Video.title == name).order_by(Video.time.desc()).first()
            
            if video_record:
                # 更新现有记录
                old_url = video_record.video_url
                video_record.video_url = url  # 更新为回调返回的URL
                db.commit()
                db_logger.info(f"[{callback_id}] 已更新数字人记录 - ID: {video_record.id}, 旧URL: {old_url}, 新URL: {url}")
                v2_logger.info(f"[{callback_id}] V2数字人创建成功，已更新数据库记录 - ID: {person_id}, 视频URL: {url}, 标题: {name}")
            else:
                # 如果没找到对应记录，创建新记录
                current_time = int(time.time())
                new_video = Video(
                    name_id="system_v2",
                    video_url=url,
                    title=name,
                    time=current_time
                )
                db.add(new_video)
                db.commit()
                db_logger.info(f"[{callback_id}] 创建新数字人记录 - ID: {new_video.id}, URL: {url}, 标题: {name}")
                v2_logger.info(f"[{callback_id}] V2数字人创建成功，已创建新数据库记录 - ID: {person_id}, 视频URL: {url}, 标题: {name}")
            
        elif status == "FAILED":
            # 数字人创建失败，记录失败信息
            v2_logger.error(f"[{callback_id}] V2数字人创建失败 - ID: {person_id}, 名称: {name}")
            db_logger.error(f"[{callback_id}] 数字人创建失败 - ID: {person_id}, 名称: {name}")
            
        else:
            # 其他状态
            v2_logger.info(f"[{callback_id}] 收到其他状态回调 - ID: {person_id}, 状态: {status}, 名称: {name}")

        # 返回成功响应给回调方
        v2_logger.info(f"[{callback_id}] ===== V2数字人回调处理完成 =====")
        return JSONResponse(status_code=200, content={'message': 'Callback processed successfully'})
        
    except Exception as e:
        v2_logger.error(f"[{callback_id}] 处理回调时出错：{e}")
        db_logger.error(f"[{callback_id}] 处理数字人回调时数据库操作出错：{e}")
        db.rollback()
        return JSONResponse(status_code=500, content={'error': 'Internal server error'})


# V2版本 - 声音克隆回调接口
@router.post("/v2/voice/callback")
async def voice_clone_callback_v2(request: Request, db: Session = Depends(get_db)):
    """
    V2版本 - 接收声音克隆创建回调
    """
    callback_id = f"V2_VOICE_CALLBACK_{int(time.time() * 1000)}"
    v2_logger.info(f"[{callback_id}] ===== 收到V2声音克隆回调请求 [{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] =====")
    v2_logger.info(f"[{callback_id}] 客户端IP: {request.client.host if request.client else 'Unknown'}")
    
    # 记录请求头
    headers_dict = dict(request.headers)
    v2_logger.info(f"[{callback_id}] 请求头: {headers_dict}")

    # 检查是否是临时声音克隆回调或内部声音克隆回调
    query_params = dict(request.query_params)
    is_temp_callback = query_params.get('temp') == '1'
    is_internal_callback = query_params.get('internal') == '1'
    temp_request_id = query_params.get('request_id')
    
    if is_temp_callback:
        v2_logger.info(f"[{callback_id}] 这是临时声音克隆回调，request_id: {temp_request_id}")
    elif is_internal_callback:
        v2_logger.info(f"[{callback_id}] 这是内部声音克隆回调（不扣费重训练），request_id: {temp_request_id}")

    # 解析回调数据
    try:
        callback_data = await request.json()
        v2_logger.info(f"[{callback_id}] 回调数据: {callback_data}")
    except Exception as e:
        v2_logger.error(f"[{callback_id}] 解析回调数据失败：{e}")
        return JSONResponse(status_code=400, content={'error': 'Invalid JSON data'})

    # 提取回调数据字段（根据您的外部API文档调整字段名）
    voice_id = callback_data.get('id') or callback_data.get('jobId')
    create_at = callback_data.get('createAt')
    name = callback_data.get('name')
    url = callback_data.get('url')
    status = callback_data.get('status')
    platform = callback_data.get('platform')
    callback_url = callback_data.get('callback')
    from_source = callback_data.get('from')
    
    # 提取tdata中的speakerId
    tdata = callback_data.get('tdata', {})
    speaker_id = tdata.get('speakerId') if isinstance(tdata, dict) else None

    v2_logger.info(f"[{callback_id}] 声音克隆回调数据解析 - ID: {voice_id}, 状态: {status}, 名称: {name}, URL: {url}, SpeakerID: {speaker_id}")

    # 处理临时声音克隆回调或内部声音克隆回调
    if (is_temp_callback or is_internal_callback) and temp_request_id:
        try:
            from app.services.external_api_v2 import update_temp_voice_result
            
            callback_type = "内部声音克隆（不扣费重训练）" if is_internal_callback else "临时声音克隆"
            
            if status == "SUCCESS":
                if speaker_id:
                    update_temp_voice_result(temp_request_id, 'success', speaker_id=speaker_id)
                    v2_logger.info(f"[{callback_id}] {callback_type}成功，已更新结果 - request_id: {temp_request_id}, speaker_id: {speaker_id}")
                else:
                    update_temp_voice_result(temp_request_id, 'failed', error='回调中缺少speakerId')
                    v2_logger.error(f"[{callback_id}] {callback_type}回调中缺少speakerId - request_id: {temp_request_id}")
            elif status == "FAILED":
                error_msg = callback_data.get('message', '声音克隆失败')
                update_temp_voice_result(temp_request_id, 'failed', error=error_msg)
                v2_logger.error(f"[{callback_id}] {callback_type}失败 - request_id: {temp_request_id}, 错误: {error_msg}")
            else:
                v2_logger.warning(f"[{callback_id}] {callback_type}回调状态未知 - request_id: {temp_request_id}, status: {status}")
            
            callback_response_msg = 'Internal voice callback processed successfully' if is_internal_callback else 'Temp voice callback processed successfully'
            return JSONResponse(status_code=200, content={'message': callback_response_msg})
            
        except Exception as e:
            v2_logger.error(f"[{callback_id}] 处理{callback_type}回调时出错：{e}")
            return JSONResponse(status_code=500, content={'error': f'Failed to process {callback_type} callback'})

    # 处理正常的声音克隆回调逻辑
    try:
        if status == "SUCCESS":
            # 声音克隆成功，更新数据库中的声音记录
            try:
                db_logger.info(f"[{callback_id}] 开始查找声音记录，voice_id: {voice_id}")
                voice_record = db.query(Voice).filter(Voice.voice_id == voice_id).first()
                
                if voice_record:
                    # 更新现有记录
                    old_url = voice_record.audio_url
                    if url:  # 如果回调提供了新的音频URL，则更新
                        voice_record.audio_url = url
                    if speaker_id:  # 保存speakerId
                        voice_record.speaker_id = speaker_id
                        v2_logger.info(f"[{callback_id}] 保存speakerId到数据库: {speaker_id}")
                    db.commit()
                    db_logger.info(f"[{callback_id}] 已更新声音记录 - ID: {voice_record.id}, 旧URL: {old_url}, 新URL: {url}, SpeakerID: {speaker_id}")
                    v2_logger.info(f"[{callback_id}] V2声音克隆成功，已更新数据库记录 - ID: {voice_id}, 音频URL: {url}, SpeakerID: {speaker_id}, 标题: {name}")
                    
                    # 通知优速AI任务成功
                    try:
                        # 使用数据库记录中保存的task_id通知优速AI
                        task_id = getattr(voice_record, 'task_id', None)
                        if task_id:
                            youshu_ai.build_status(task_id=task_id, status='success', remake='V2声音克隆成功')
                            v2_logger.info(f"[{callback_id}] 已通知优速AI任务成功 - TaskID: {task_id}")
                        else:
                            v2_logger.warning(f"[{callback_id}] 声音记录缺少taskId，无法通知优速AI - ID: {voice_id}")
                    except Exception as e:
                        v2_logger.error(f"[{callback_id}] 通知优速AI失败: {e}")
                    
                else:
                    # 如果没找到对应记录，记录警告但不创建新记录（因为应该在创建时已经有记录了）
                    v2_logger.warning(f"[{callback_id}] 未找到对应的声音记录 - ID: {voice_id}, 名称: {name}")
                    db_logger.warning(f"[{callback_id}] 数据库中未找到voice_id为{voice_id}的记录")
                    
            except Exception as query_error:
                if "Unknown column" in str(query_error):
                    db.rollback()
                    v2_logger.warning(f"[{callback_id}] 数据库查询失败，可能缺少字段: {query_error}")
                    db_logger.warning(f"[{callback_id}] 数据库字段问题，使用兼容模式查询")
                    # 尝试不查询新字段的方式
                    try:
                        voice_record = db.query(Voice).filter(Voice.voice_id == voice_id).first()
                        if voice_record and url:
                            old_url = voice_record.audio_url
                            voice_record.audio_url = url
                            # 尝试设置speaker_id，如果失败就跳过
                            try:
                                if speaker_id:
                                    voice_record.speaker_id = speaker_id
                                    v2_logger.info(f"[{callback_id}] 保存speakerId到数据库（兼容模式）: {speaker_id}")
                            except:
                                v2_logger.warning(f"[{callback_id}] 无法保存speakerId，可能需要执行数据库迁移")
                            db.commit()
                            db_logger.info(f"[{callback_id}] 已更新声音记录（兼容模式） - ID: {voice_record.id}, 旧URL: {old_url}, 新URL: {url}")
                            v2_logger.info(f"[{callback_id}] V2声音克隆成功，已更新数据库记录（兼容模式） - ID: {voice_id}")
                    except Exception as compat_error:
                        db_logger.error(f"[{callback_id}] 兼容模式更新也失败：{compat_error}")
                        db.rollback()
                        raise compat_error
                else:
                    raise query_error
            
        elif status == "FAILED":
            # 声音克隆失败，可以考虑删除或标记失败状态
            v2_logger.error(f"[{callback_id}] V2声音克隆失败 - ID: {voice_id}, 名称: {name}")
            db_logger.error(f"[{callback_id}] 声音克隆失败 - ID: {voice_id}, 名称: {name}")
            
            try:
                # 可选：删除失败的记录
                db_logger.info(f"[{callback_id}] 开始删除失败的声音记录，voice_id: {voice_id}")
                voice_record = db.query(Voice).filter(Voice.voice_id == voice_id).first()
                if voice_record:
                    # 通知优速AI任务失败
                    try:
                        # 使用数据库记录中保存的task_id通知优速AI
                        task_id = getattr(voice_record, 'task_id', None)
                        if task_id:
                            youshu_ai.build_status(task_id=task_id, status='failed', remake='V2声音克隆失败')
                            v2_logger.info(f"[{callback_id}] 已通知优速AI任务失败 - TaskID: {task_id}")
                    except Exception as e:
                        v2_logger.error(f"[{callback_id}] 通知优速AI失败: {e}")
                    
                    db.delete(voice_record)
                    db.commit()
                    db_logger.info(f"[{callback_id}] 已删除失败的声音克隆记录 - ID: {voice_record.id}")
                    v2_logger.info(f"[{callback_id}] 已删除失败的声音克隆记录 - ID: {voice_id}")
                else:
                    v2_logger.warning(f"[{callback_id}] 未找到要删除的声音记录 - ID: {voice_id}")
                    
            except Exception as query_error:
                if "Unknown column" in str(query_error):
                    db.rollback()
                    v2_logger.warning(f"[{callback_id}] 数据库查询失败，可能缺少字段: {query_error}")
                    db_logger.warning(f"[{callback_id}] 数据库字段问题，使用兼容模式删除")
                    # 尝试不查询新字段的方式删除记录
                    try:
                        voice_record = db.query(Voice).filter(Voice.voice_id == voice_id).first()
                        if voice_record:
                            db.delete(voice_record)
                            db.commit()
                            db_logger.info(f"[{callback_id}] 已删除失败的声音记录（兼容模式） - ID: {voice_record.id}")
                            v2_logger.info(f"[{callback_id}] 已删除失败的声音克隆记录（兼容模式） - ID: {voice_id}")
                    except Exception as compat_error:
                        db_logger.error(f"[{callback_id}] 兼容模式删除也失败：{compat_error}")
                        db.rollback()
                        raise compat_error
                else:
                    raise query_error
            
        else:
            # 其他状态
            v2_logger.info(f"[{callback_id}] 收到其他状态回调 - ID: {voice_id}, 状态: {status}, 名称: {name}")

        # 返回成功响应给回调方
        v2_logger.info(f"[{callback_id}] ===== V2声音克隆回调处理完成 =====")
        return JSONResponse(status_code=200, content={'message': 'Voice callback processed successfully'})
        
    except Exception as e:
        v2_logger.error(f"[{callback_id}] 处理声音克隆回调时出错：{e}")
        db_logger.error(f"[{callback_id}] 处理声音克隆回调时数据库操作出错：{e}")
        db.rollback()
        return JSONResponse(status_code=500, content={'error': 'Internal server error'}) 


# V2版本 - 创建作品接口
@router.post("/v2/videomix/create")
async def create_videomix_v2_endpoint(request: Request, db: Session = Depends(get_db)):
    """
    V2版本 - 创建作品接口（使用独立的jobs_v2表）
    """
    request_id = f"V2_VIDEOMIX_{int(time.time() * 1000)}"
    v2_logger.info(f"[{request_id}] ===== V2作品创建请求开始 =====")
    v2_logger.info(f"[{request_id}] 收到请求：{request.method} {request.url.path}")
    v2_logger.info(f"[{request_id}] 客户端IP: {request.client.host if request.client else 'Unknown'}")
    
    # 记录请求头
    headers_dict = dict(request.headers)
    v2_logger.info(f"[{request_id}] 请求头: {headers_dict}")

    # 验证 Content-Type
    if request.headers.get('content-type') != 'application/json':
        v2_logger.error(f"[{request_id}] Content-Type 非 application/json")
        raise HTTPException(status_code=400, detail='Content-Type must be application/json')
    
    # 提取 headers 中的 token 值
    token = request.headers.get('Authorization')
    if not token:
        v2_logger.error(f"[{request_id}] 请求头中缺少 Authorization token")
        return JSONResponse(status_code=401, content={"code": 401, "msg": "缺少 Authorization token"})

    v2_logger.info(f"[{request_id}] 提取到的 token: {token}")
    print("token:", token)

    # 验证token并扣除点数 - 使用项目ID 48（与V1作品创建保持一致）
    v2_logger.info(f"[{request_id}] 开始验证token，项目ID: 48")
    user_info = youshu_ai.get_current_user_information(project=48, token=token)
    v2_logger.info(f"[{request_id}] 优速AI验证结果: {user_info}")
    print("user_info:", user_info)

    # 从 user_info 中获取统一的 code 和 msg
    code = user_info.get("code", 500)  # 如果没拿到 code，就默认为 500
    msg = user_info.get("msg", "未知错误")

    # 根据 code 判断是否继续执行
    if code == 200:
        # 表示验证成功，可以继续后续逻辑
        verify_taskId = user_info.get("taskId")
        jssign = user_info.get("jssign")
        v2_logger.info(f"[{request_id}] Token验证成功，taskId: {verify_taskId}, jssign: {jssign}")
    else:
        # 只要 code != 200，就将错误直接返回给前端
        v2_logger.error(f"[{request_id}] Token验证失败: code={code}, msg={msg}")
        return JSONResponse(status_code=code, content={"code": code, "msg": msg})

    # 解析 JSON 数据
    try:
        data = await request.json()
        v2_logger.info(f"[{request_id}] 接收到的数据：{data}")
    except Exception as e:
        v2_logger.error(f"[{request_id}] 请求体中缺少 JSON 数据：{e}")
        raise HTTPException(status_code=400, detail='Missing JSON data in request body')

    # 提取参数（与V1保持一致的参数名）
    name_id = data.get('name_id')
    video_url = data.get('video_url')  # 对应personUrl
    voice_id = data.get('voice_id')    # 用于查找speaker_id
    voice_type = data.get('voice_type') # 对应voiceType
    text = data.get('text')            # 对应content
    title = data.get('title')          # 对应name
    only_generate_audio = data.get('only_generate_audio', 0)  # V2版本固定为0

    v2_logger.info(f"[{request_id}] 解析参数 - name_id: {name_id}, video_url: {video_url}, voice_id: {voice_id}, voice_type: {voice_type}, text: {text}, title: {title}, only_generate_audio: {only_generate_audio}")

    if not all([name_id, video_url, voice_id, voice_type, text, title]):
        v2_logger.error(f"[{request_id}] 缺少必要参数")
        return JSONResponse(status_code=400, content={'error': 'name_id, video_url, voice_id, voice_type, text, title are required'})

    # 检查用户是否存在，不存在则创建
    user = db.query(User).filter(User.name_id == name_id).first()
    if not user:
        v2_logger.info(f"[{request_id}] 用户不存在，自动为其创建用户记录，name_id={name_id}")
        db_logger.info(f"[{request_id}] 创建新用户: {name_id}")
        user = User(name_id=name_id)
        db.add(user)
        db.commit()
        db.refresh(user)
        v2_logger.info(f"[{request_id}] 已创建新用户，name_id={user.name_id}")
    else:
        db_logger.info(f"[{request_id}] 用户已存在: {name_id}")

    # 根据voice_id查询数据库获取speaker_id和v2_voice_type
    try:
        db_logger.info(f"[{request_id}] 开始查询声音记录，voice_id: {voice_id}")
        voice_record = db.query(Voice).filter(Voice.voice_id == voice_id).first()
        
        if voice_record:
            speaker_id = voice_record.speaker_id
            # 使用数据库中的v2_voice_type作为实际的voiceType参数
            db_voice_type = voice_record.v2_voice_type or 'lite'  # 如果为空则默认使用lite
            v2_logger.info(f"[{request_id}] 找到声音记录 - voice_id: {voice_id}, speaker_id: {speaker_id}, 标题: {voice_record.title}, v2_voice_type: {db_voice_type}")
            
            if not speaker_id:
                v2_logger.warning(f"[{request_id}] 声音记录中缺少speaker_id，开始调用V2声音克隆获取 - voice_id: {voice_id}")
                
                # 检查声音记录是否有audio_url
                if not voice_record.audio_url:
                    v2_logger.error(f"[{request_id}] 声音记录中缺少audio_url，无法进行声音克隆 - voice_id: {voice_id}")
                    return JSONResponse(status_code=400, content={'error': f'声音记录中缺少audio_url，voice_id: {voice_id}'})
                
                try:
                    # 导入内部声音克隆函数（不扣费）
                    from app.services.external_api_v2 import create_voice_clone_internal
                    
                    # 准备声音克隆数据 - 使用数据库中的v2_voice_type
                    voice_clone_data = {
                        'name': f'internal_retrain_{voice_record.title}_{request_id}',
                        'url': voice_record.audio_url,
                        'voiceType': db_voice_type  # 使用数据库中的v2_voice_type
                    }
                    
                    v2_logger.info(f"[{request_id}] 开始内部声音克隆（不扣费重训练） - 数据: {voice_clone_data}")
                    
                    # 调用内部声音克隆（不扣费）
                    speaker_id, success, error_message = await create_voice_clone_internal(voice_clone_data, request_id)
                    
                    if success and speaker_id:
                        v2_logger.info(f"[{request_id}] 内部声音克隆（不扣费）成功，获取到speaker_id: {speaker_id}")
                        
                        # 更新数据库中的speaker_id
                        try:
                            voice_record.speaker_id = speaker_id
                            db.commit()
                            db_logger.info(f"[{request_id}] 已更新声音记录的speaker_id - voice_id: {voice_id}, speaker_id: {speaker_id}")
                            v2_logger.info(f"[{request_id}] 声音记录已更新speaker_id（通过内部不扣费重训练），继续创建作品")
                        except Exception as update_error:
                            v2_logger.error(f"[{request_id}] 更新speaker_id到数据库失败: {update_error}")
                            db.rollback()
                            # 即使更新失败，也继续使用获取到的speaker_id创建作品
                    else:
                        v2_logger.error(f"[{request_id}] 内部声音克隆（不扣费）失败: {error_message}")
                        return JSONResponse(status_code=500, content={'error': f'内部声音克隆失败: {error_message}'})
                        
                except Exception as clone_error:
                    v2_logger.error(f"[{request_id}] 调用内部声音克隆时出错: {clone_error}")
                    return JSONResponse(status_code=500, content={'error': f'内部声音克隆异常: {str(clone_error)}'})
        elif not voice_record and voice_type == 10:
            # 查询该
            # 使用数据库中的v2_voice_type作为实际的voiceType参数
            db_voice_type = 'lite'  # 如果为空则默认使用lite
            speaker_id = None
            v2_logger.info(f"[{request_id}] 没有找到公共音色的声音记录，开始调用V2声音克隆获取 - voice_id: {voice_id}")
            if speaker_id is None:
                v2_logger.warning(f"[{request_id}] 公共音色可能没有克隆过，声音记录中缺少speaker_id，开始调用V2声音克隆获取 - voice_id: {voice_id}")

                # 初始化公共音色URL
                gonggong_voice_url = ""

                # 获取公共音色数据
                gonggong_voice_data = settings.GONGGONG_AUDIO_URL.get("data")
                # 遍历公共音色数据，获取公共音色ID对应的URL
                for item in gonggong_voice_data:
                    if item.get("voice_id") == voice_id:
                        gonggong_voice_url = item.get("audio_url")
                        gonggong_voice_title = item.get("title")  # 使用自定义标题或默认值
                        break
                
                if not gonggong_voice_url:
                    v2_logger.error(f"[{request_id}] 没有找到公共音色ID对应的URL - voice_id: {voice_id}")
                    return JSONResponse(status_code=400, content={'error': f'没有找到公共音色ID对应的URL，voice_id: {voice_id}'})
                
                try:
                    # 导入内部声音克隆函数（不扣费）
                    from app.services.external_api_v2 import create_voice_clone_internal
                    
                    # 准备声音克隆数据 - 使用数据库中的v2_voice_type
                    voice_clone_data = {
                        'name': f'internal_retrain_{gonggong_voice_title}_{request_id}',
                        'url': gonggong_voice_url,
                        'voiceType': db_voice_type  # 使用数据库中的v2_voice_type
                    }
                    
                    v2_logger.info(f"[{request_id}] 公共音色开始内部声音克隆（不扣费重训练） - 数据: {voice_clone_data}")
                    
                    # 调用内部声音克隆（不扣费）
                    speaker_id, success, error_message = await create_voice_clone_internal(voice_clone_data, request_id)
                    
                    if success and speaker_id:
                        v2_logger.info(f"[{request_id}] 公共音色内部声音克隆（不扣费）成功，获取到speaker_id: {speaker_id}")
                        
                        # >>>>> 修改点：创建新的声音记录 <<<<<
                        try:
                            # 创建新的公共音色记录
                            new_voice = Voice(
                                name_id="-1",
                                voice_id=voice_id,
                                type=voice_type,
                                time=int(time.time()),
                                voice_type=voice_type,
                                audio_url=gonggong_voice_url,
                                title=gonggong_voice_title,
                                v2_voice_type=db_voice_type,
                                speaker_id=speaker_id,

                            )
                            db.add(new_voice)
                            db.commit()
                            db.refresh(new_voice)
                            voice_record = new_voice  # 更新当前引用
                            db_logger.info(f"[{request_id}] 已创建新的公共音色记录 - voice_id: {voice_id}, speaker_id: {speaker_id}")
                            v2_logger.info(f"[{request_id}] 公共音色记录已创建并保存speaker_id")
                        except Exception as create_error:
                            v2_logger.error(f"[{request_id}] 创建公共音色记录失败: {create_error}")
                            db.rollback()
                            # 即使更新失败，也继续使用获取到的speaker_id创建作品
                    else:
                        v2_logger.error(f"[{request_id}] 公共音色内部声音克隆（不扣费）失败: {error_message}")
                        return JSONResponse(status_code=500, content={'error': f'公共音色内部声音克隆失败: {error_message}'})
                        
                except Exception as clone_error:
                    v2_logger.error(f"[{request_id}] 调用内部声音克隆（公共音色）时出错: {clone_error}")
                    return JSONResponse(status_code=500, content={'error': f'公共音色内部声音克隆异常: {str(clone_error)}'})
        else:
            v2_logger.error(f"[{request_id}] 未找到对应的声音记录 - voice_id: {voice_id}")
            return JSONResponse(status_code=404, content={'error': f'未找到对应的声音记录，voice_id: {voice_id}'})
            
    except Exception as e:
        v2_logger.error(f"[{request_id}] 查询声音记录时出错：{e}")
        db_logger.error(f"[{request_id}] 数据库查询失败：{e}")
        return JSONResponse(status_code=500, content={'error': '查询声音记录失败'})

    # 最终检查speaker_id
    if not speaker_id:
        v2_logger.error(f"[{request_id}] 无法获取有效的speaker_id - voice_id: {voice_id}")
        return JSONResponse(status_code=500, content={'error': '无法获取有效的speaker_id'})

    # 构建外部API调用数据（使用speaker_id作为voiceTid，使用数据库中的v2_voice_type作为voiceType）
    external_data = {
        'name': title,
        'personUrl': video_url,
        'callback': settings.V2_VIDEOMIX_CALLBACK_URL,
        'content': text,
        'voiceTid': speaker_id,  # 使用从数据库查询到的speaker_id
        'voiceType': db_voice_type  # 使用数据库中的v2_voice_type
    }
    v2_logger.info(f"[{request_id}] 构建外部API调用数据: {external_data}")
    v2_logger.info(f"[{request_id}] 使用speaker_id: {speaker_id} 作为voiceTid（原voice_id: {voice_id}），使用数据库v2_voice_type: {db_voice_type} 作为voiceType")

    # 调用V2版本的外部 API 创建作品
    try:
        external_api_logger.info(f"[{request_id}] 开始调用V2作品创建API")
        external_api_logger.info(f"[{request_id}] API地址: {settings.EXTERNAL_VIDEOMIX_V2_URL}")
        external_api_logger.info(f"[{request_id}] 发送数据: {external_data}")
        
        response_data, status_code = await create_videomix_v2(external_data)
        
        external_api_logger.info(f"[{request_id}] V2作品创建API响应：状态码={status_code}, 数据={response_data}")
        v2_logger.info(f"[{request_id}] V2作品创建API响应：状态码={status_code}, 数据={response_data}")
        
        if status_code == 200:
            # 如果外部API调用成功，将任务信息保存到jobs_v2表
            try:
                current_time = int(time.time())
                db_logger.info(f"[{request_id}] 开始数据库操作，当前时间戳: {current_time}")
                
                # 从响应数据中提取jobId
                job_id = response_data.get('data', {}).get('jobId')
                if not job_id:
                    v2_logger.error(f"[{request_id}] 外部API响应中缺少jobId")
                    return JSONResponse(status_code=500, content={'error': '外部API响应格式错误'})
                
                v2_logger.info(f"[{request_id}] 获取到jobId: {job_id}")
                
                # 创建V2作品记录（使用JobV2模型）- 优化：创建时不存储video_url
                new_job_v2 = JobV2(
                    name_id=name_id,
                    job_id=job_id,
                    video_url=None,  # 优化：创建时不存储，等待回调成功后再添加
                    voice_id=voice_id,  # 保存原始的voice_id用于关联
                    voice_type=voice_type,
                    text=text,
                    title=title,
                    only_generate_audio=bool(only_generate_audio),
                    found_time=current_time,
                    task_id=verify_taskId,  # 保存优速AI的taskId
                    original_video_url=video_url,  # 保存原始视频URL（用于外部API调用）
                    status=3,  # 初始状态为处理中
                    message="作品正在生成中，等待回调更新"
                )
                db.add(new_job_v2)
                db.commit()
                
                db_logger.info(f"[{request_id}] V2作品记录已保存到jobs_v2表（video_url待回调更新） - 用户: {name_id}, 标题: {title}, JobID: {job_id}, TaskID: {verify_taskId}, VoiceID: {voice_id}, SpeakerID: {speaker_id}, 作品ID: {new_job_v2.id}")
                v2_logger.info(f"[{request_id}] V2作品创建任务已保存到jobs_v2表（优化：video_url待回调成功后更新） - 用户: {name_id}, 标题: {title}, JobID: {job_id}, TaskID: {verify_taskId}, VoiceID: {voice_id}, SpeakerID: {speaker_id}")
                
                # 返回成功响应
                return JSONResponse(status_code=200, content={
                    'code': 200,
                    'message': 'V2作品创建任务已提交',
                    'data': {
                        'job_id': job_id,
                        'task_id': verify_taskId,
                        'title': title,
                        'voice_id': voice_id,
                        'speaker_id': speaker_id,
                        'status': 'processing'
                    }
                })
                
            except Exception as e:
                db_logger.error(f"[{request_id}] 数据库操作失败：{e}")
                v2_logger.error(f"[{request_id}] 保存V2作品记录到数据库失败：{e}")
                db.rollback()
                return JSONResponse(status_code=500, content={'error': '数据库操作失败'})
        else:
            v2_logger.error(f"[{request_id}] V2外部API调用失败：状态码={status_code}, 数据={response_data}")
            return JSONResponse(status_code=500, content={'error': '外部API调用失败'})
            
    except Exception as e:
        external_api_logger.error(f"[{request_id}] V2外部API调用异常：{e}")
        v2_logger.error(f"[{request_id}] V2外部API调用异常：{e}")
        return JSONResponse(status_code=500, content={'error': '外部API调用异常'})
    
    finally:
        v2_logger.info(f"[{request_id}] ===== V2作品创建请求结束 =====")


# V2版本 - 作品创建回调接口
@router.post("/v2/videomix/callback")
async def videomix_callback_v2(request: Request, db: Session = Depends(get_db)):
    """
    V2版本 - 接收作品创建回调（使用独立的jobs_v2表）
    """
    callback_id = f"V2_VIDEOMIX_CALLBACK_{int(time.time() * 1000)}"
    v2_logger.info(f"[{callback_id}] ===== 收到V2作品创建回调请求 [{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] =====")
    v2_logger.info(f"[{callback_id}] 客户端IP: {request.client.host if request.client else 'Unknown'}")
    
    # 记录请求头
    headers_dict = dict(request.headers)
    v2_logger.info(f"[{callback_id}] 请求头: {headers_dict}")

    # 解析回调数据
    try:
        callback_data = await request.json()
        v2_logger.info(f"[{callback_id}] 回调数据: {callback_data}")
    except Exception as e:
        v2_logger.error(f"[{callback_id}] 解析回调数据失败：{e}")
        return JSONResponse(status_code=400, content={'error': 'Invalid JSON data'})

    # 解析回调数据的关键字段
    try:
        # 基本信息
        work_id = callback_data.get('id')  # 外部API创建时返回的jobId
        status = callback_data.get('status')  # SUCCESS/FAILED
        name = callback_data.get('name')
        main_url = callback_data.get('url')
        
        # tdata中的详细信息
        tdata = callback_data.get('tdata', {})
        internal_job_id = tdata.get('jobId')  # 内部处理的jobId（不同于创建时返回的）
        video_url = tdata.get('videoUrl')
        duration = tdata.get('duration')
        error_message = tdata.get('errorMessage', '')
        
        v2_logger.info(f"[{callback_id}] 作品创建回调数据解析 - 外部ID: {work_id}, 状态: {status}, 名称: {name}, 主URL: {main_url}, 内部JobID: {internal_job_id}, 视频URL: {video_url}, 时长: {duration}")
        
    except Exception as e:
        v2_logger.error(f"[{callback_id}] 解析回调数据字段失败：{e}")
        return JSONResponse(status_code=400, content={'error': 'Invalid callback data format'})

    if status == 'SUCCESS':
        try:
            # 使用外部API创建时返回的jobId（work_id）来查找jobs_v2表中的记录
            db_logger.info(f"[{callback_id}] 开始查找V2作品记录，使用外部API返回的job_id: {work_id}")
            job_record = db.query(JobV2).filter(JobV2.job_id == work_id).first()
            
            if job_record:
                v2_logger.info(f"[{callback_id}] 找到对应的V2作品记录 - 数据库ID: {job_record.id}, JobID: {job_record.job_id}, 标题: {job_record.title}")
                
                # 处理视频URL并上传到TOS
                if video_url:
                    v2_logger.info(f"[{callback_id}] 开始上传视频到TOS - 源URL: {video_url}")
                    
                    try:
                        # 导入TOS上传服务
                        from app.services.huoshan_oss import upload_file
                        
                        # 从URL中提取文件名（去掉.mp4扩展名）
                        import re
                        filename_match = re.search(r'/([^/]+)\.mp4$', video_url)
                        if filename_match:
                            filename = filename_match.group(1)
                        else:
                            # 如果无法提取，使用UUID作为文件名
                            import uuid
                            filename = str(uuid.uuid4())
                        
                        v2_logger.info(f"[{callback_id}] 提取的文件名: {filename}")
                        
                        # 上传视频到TOS
                        upload_result = await upload_file(settings.OSS_VIDEO_TASK, filename, video_url)
                        v2_logger.info(f"[{callback_id}] 视频已上传到TOS: {upload_result}")
                        
                        if upload_result and upload_result.get('code') == 200:
                            tos_video_url = upload_result.get('oss_url')
                            
                            # 更新数据库记录
                            current_time = int(time.time())
                            expire_time = current_time + (30 * 24 * 60 * 60)  # 30天后到期
                            
                            job_record.video_url = tos_video_url  # 更新为TOS URL
                            job_record.external_video_url = video_url  # 保存外部API返回的原始URL
                            job_record.video_duration = duration
                            job_record.video_time = current_time
                            job_record.status = 1  # 成功状态
                            job_record.message = "V2作品创建成功"
                            job_record.expire_time = expire_time
                            
                            db.commit()
                            
                            db_logger.info(f"[{callback_id}] 已更新V2作品记录（优化：回调时首次填入video_url） - ID: {job_record.id}, 原始URL: {job_record.original_video_url}, TOS URL: {tos_video_url}, 时长: {duration}")
                            v2_logger.info(f"[{callback_id}] V2作品创建成功，已更新jobs_v2表记录（优化：回调时填入video_url） - JobID: {work_id}, TOS视频URL: {tos_video_url}, 时长: {duration}, 标题: {job_record.title}")
                            
                            # 通知优速AI任务完成
                            try:
                                youshu_ai.build_status(task_id=job_record.task_id, status='success', remake='V2作品创建成功')
                                v2_logger.info(f"[{callback_id}] 已通知优速AI任务成功 - TaskID: {job_record.task_id}")
                            except Exception as notify_error:
                                v2_logger.error(f"[{callback_id}] 通知优速AI失败: {notify_error}")
                            
                        else:
                            # TOS上传失败，但仍保存原始URL
                            v2_logger.warning(f"[{callback_id}] TOS上传失败，保存原始视频URL")
                            current_time = int(time.time())
                            expire_time = current_time + (30 * 24 * 60 * 60)
                            
                            job_record.video_url = video_url  # 使用原始URL
                            job_record.external_video_url = video_url
                            job_record.video_duration = duration
                            job_record.video_time = current_time
                            job_record.status = 1
                            job_record.message = "V2作品创建成功（TOS上传失败）"
                            job_record.expire_time = expire_time
                            
                            db.commit()
                            
                            # 通知优速AI任务完成
                            try:
                                youshu_ai.build_status(task_id=job_record.task_id, status='success', remake='V2作品创建成功')
                                v2_logger.info(f"[{callback_id}] 已通知优速AI任务成功 - TaskID: {job_record.task_id}")
                            except Exception as notify_error:
                                v2_logger.error(f"[{callback_id}] 通知优速AI失败: {notify_error}")
                        
                    except Exception as upload_error:
                        v2_logger.error(f"[{callback_id}] 视频处理失败: {upload_error}")
                        # 即使上传失败，也要更新记录状态
                        job_record.status = 1
                        job_record.message = f"V2作品创建成功，但视频处理失败: {str(upload_error)}"
                        job_record.video_duration = duration
                        job_record.video_time = int(time.time())
                        db.commit()
                        
                        # 通知优速AI任务完成
                        try:
                            youshu_ai.build_status(task_id=job_record.task_id, status='success', remake='V2作品创建成功')
                            v2_logger.info(f"[{callback_id}] 已通知优速AI任务成功 - TaskID: {job_record.task_id}")
                        except Exception as notify_error:
                            v2_logger.error(f"[{callback_id}] 通知优速AI失败: {notify_error}")
                
                else:
                    v2_logger.warning(f"[{callback_id}] 回调数据中没有视频URL")
                    job_record.status = 1
                    job_record.message = "V2作品创建成功，但缺少视频URL"
                    db.commit()
                    
            else:
                v2_logger.error(f"[{callback_id}] 在jobs_v2表中未找到对应的作品记录，job_id: {work_id}")
                return JSONResponse(status_code=404, content={'error': 'Job record not found in jobs_v2 table'})
                
        except Exception as e:
            v2_logger.error(f"[{callback_id}] 处理成功回调时出错：{e}")
            db.rollback()
            return JSONResponse(status_code=500, content={'error': 'Failed to process success callback'})
    
    elif status == 'FAILED':
        try:
            # 更新失败状态
            db_logger.info(f"[{callback_id}] 开始更新失败的V2作品记录，job_id: {work_id}")
            job_record = db.query(JobV2).filter(JobV2.job_id == work_id).first()
            if job_record:
                job_record.status = 2  # 设置为失败状态
                job_record.message = f"V2作品创建失败: {error_message}"
                job_record.video_time = int(time.time())
                db.commit()
                
                v2_logger.info(f"[{callback_id}] 已更新V2作品失败状态 - JobID: {work_id}, 错误信息: {error_message}")
                
                # 通知优速AI任务失败
                try:
                    youshu_ai.build_status(task_id=job_record.task_id, status='failed', remake=f'V2作品创建失败: {error_message}')
                    v2_logger.info(f"[{callback_id}] 已通知优速AI任务失败 - TaskID: {job_record.task_id}")
                except Exception as notify_error:
                    v2_logger.error(f"[{callback_id}] 通知优速AI失败: {notify_error}")
                    
            else:
                v2_logger.error(f"[{callback_id}] 在jobs_v2表中未找到失败的作品记录，job_id: {work_id}")
                return JSONResponse(status_code=404, content={'error': 'Failed job record not found in jobs_v2 table'})
                
        except Exception as e:
            v2_logger.error(f"[{callback_id}] 处理失败回调时出错：{e}")
            db.rollback()
            return JSONResponse(status_code=500, content={'error': 'Failed to process failure callback'})
    
    else:
        v2_logger.warning(f"[{callback_id}] 未知的回调状态: {status}")
        return JSONResponse(status_code=400, content={'error': f'Unknown callback status: {status}'})
    
    v2_logger.info(f"[{callback_id}] ===== V2作品创建回调处理完成 =====")
    return JSONResponse(status_code=200, content={'message': 'V2 Callback processed successfully'}) 